﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Web;

namespace HeroldIT.Dnn.JQuery
{
    /// <summary>
    /// A helper class for ensuring the JQuery infrastructure.
    /// </summary>
    public static class JQuery
    {
        #region constants

        private const string JQueryVersion = "1.5.2";
        private static readonly string RegisteredOnDocumentReadyBlocksKey = typeof(JQuery).FullName + "$RegisteredOnDocumentReadyBlocks";

        #endregion

        #region extension methods

        /// <summary>
        /// Registers jQuery for the given page.
        /// </summary>
        /// <param name="page">The page for which to register jQuery.</param>
        public static void RegisterJQuery(this Page page)
        {
            if (null == page)
                throw new ArgumentNullException("page");

            page.ClientScript.RegisterClientScriptInclude(typeof(JQuery), "jquery-" + JQueryVersion, VirtualPathUtility.ToAbsolute("~/DesktopModules/HeroldIT.JQuery/js/jquery-" + JQueryVersion + ".min.js"));
            page.ClientScript.RegisterClientScriptBlock(typeof(JQuery), "jQuery.noConflict", "jQuery.noConflict();", true);
        }

        private static List<string> GetRegisteredJQueryOnDocumentReadyBlocks(this Page page)
        {
            if (null == page)
                throw new ArgumentNullException("page");

            List<string> blocks = page.Items[RegisteredOnDocumentReadyBlocksKey] as List<string>;
            if (null == blocks)
            {
                blocks = new List<string>();
                page.Items[RegisteredOnDocumentReadyBlocksKey] = blocks;
            }
            return blocks;
        }

        /// <summary>
        /// Register a javascript block for execution in the jQuery document ready event.
        /// </summary>
        /// <param name="page">The page on which to register the javascript block.</param>
        /// <param name="script">The script block to execute in the document ready event.</param>
        public static void RegisterJQueryOnDocumentReadyBlock(this Page page, string script)
        {
            if (null == page)
                throw new ArgumentNullException("page");
            if (String.IsNullOrEmpty(script))
                return;

            List<string> blocks = page.GetRegisteredJQueryOnDocumentReadyBlocks();
            blocks.Add(script);
            page.PreRenderComplete += page_PreRenderComplete;
        }

        /// <summary>
        /// Gets the <paramref name="control"/>'s ClientID prepared and escaped for use as a jQuery selector string.
        /// </summary>
        /// <param name="control">The control to get the ClientID from.</param>
        /// <returns>The <paramref name="control"/>'s ClientID prepared and escaped for use as a jQuery selector string.</returns>
        public static string JQueryClientID(this Control control)
        {
            if (null == control)
                throw new ArgumentNullException("control");

            return "#" + control.ClientID.Replace(".", "\\\\.");
        }

        #endregion

        #region static event handlers

        private static void page_PreRenderComplete(object sender, EventArgs e)
        {
            Page page = (Page) sender;
            List<string> blocks = page.GetRegisteredJQueryOnDocumentReadyBlocks();
            if (blocks.Count > 0)
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("jQuery(function($){");
                for (int i = 0; i < blocks.Count; i++)
                {
                    string block = blocks[i];
                    sb.Append(block);
                    if (!block.Trim().EndsWith(";"))
                    {
                        sb.Append(";");
                    }
                }
                sb.Append("});");
                page.ClientScript.RegisterClientScriptBlock(typeof(JQuery), "OnDocumentReadyBlocks", sb.ToString(), true);
            }
        }

        #endregion
    }
}
